﻿#pragma once
#include "AsMathBasic.h"

class AS_MATH_API AsMathLine {
public:
	AsMathLine();
	AsMathLine(double a, double b, double c);

private:
	double m_a;
	double m_b;
	double m_c;
	double m_k;
	cv::Point2f m_p1;
	cv::Point2f m_p2;

public:
	static AsMathLine vertical(double x0);
	static AsMathLine horizontal(double y0);
	static AsMathLine fromKB(double k, double b);
	static AsMathLine fromPointK(const cv::Point2f& p, double k);
	static AsMathLine fromPoints(const cv::Point2f& p1, const cv::Point2f& p2);
	static AsMathLine fromVec4f(cv::Vec4f line);

public:
	std::string tostr() const;

public:
	bool isValid() const;
	double getA() const;
	double getB() const;
	double getC() const;
	double getK() const;
	cv::Point2f getP1() const;
	cv::Point2f getP2() const;
	double getY(double x) const;
	double getX(double y) const;
	std::pair<cv::Point2f, cv::Point2f> getLine(cv::Rect range) const;

public:
	double getLength() const;
	double calcDistance(const cv::Point2f& p) const;
	double calcDistanceSigned(const cv::Point2f& p) const;

public:
	bool isVertical() const;
	bool isHorizontal() const;
	bool isParallel(const AsMathLine& line) const;
	bool isIntersection(const AsMathLine& line) const;
	bool isCoincide(const AsMathLine& line) const;
	bool isOrthogonality(const AsMathLine& line) const;

public:
	void translate(cv::Point2f dist);
	void translateInAltitude(double dist);

public:
	double getAngle(const AsMathLine& line) const;

	cv::Point2f getNode(const AsMathLine& line) const;
	std::vector<cv::Point2f> getNodes(const cv::Rect& rect) const;
	std::vector<cv::Point2f> getNodes(const std::vector<cv::Point2f>& points) const;

	std::vector<cv::Point> getNearbyPoints(const std::vector<cv::Point>& points, double dist_thresh = 1.0);
	std::vector<cv::Point2f> getNearbyPoints(const std::vector<cv::Point2f>& points, double dist_thresh = 1.0);
	int getNearbyCount(const std::vector<cv::Point>& points, double dist_thresh = 1.0);
	int getNearbyCount(const std::vector<cv::Point2f>& points, double dist_thresh = 1.0);

public:
	cv::Point2f getAltitudePoint(const cv::Point2f& p) const;
	double toAltitudeK() const;
	AsMathLine toAltitude(const cv::Point2f& p) const;
	std::vector<cv::Point> getPoints(cv::Rect range, int interval = 1) const;
	std::vector<cv::Point> getPoints(const cv::Point& center, double radius, int interval = 1);

};
